Research Context
A lab anchored in humanities with a focus on the dissemination of methods and tools for the analysis and representation of spatial information.
https://riate.cnrs.fr/
Tools
R Packages
A set of R packages osrm, potential, MTA… github.com/riatelab
Reproducible Research Promotion
SIGR
A summer school on Reproducible Research for Geographic Information Sciences
Reproducible Cartography
Why?
Les cartes, comme les autres productions graphiques ou statistiques sont des éléments à parts entières des études scientifiques.
Giraud and Lambert (2017)
La plupart des cartes produites dans un contexte académique sont issues de processus complexes.
Elles sont souvent produites en utilisant une grande variété de logiciels et de formats.
Cette variété de formats et de logiciels rend difficile la reproduction des cartes.
Simplifier les chaines de traitement pour couvrir les différentes étapes de la construction cartographique.
How?
With R and its spatial ecosystem !
sf, corner stone of the R spatial ecosystem
Pebesma and Bivand (2020)
mapsf
typical workflow
mf_map()
mf_map() is the main function of the package.
mf_map(x = objet_sf,
var = "variable",
type = "map type",
...)
?mapsf
Map mayout
Example
- Base map:
mtq <- mf_get_mtq()
# Plot the base map
mf_map(x = mtq)
- Choropleth map with default parameters:
mtq <- mf_get_mtq()
# Plot a choropleth map
mf_map(x = mtq, var = "MED", type = "choro")
- Parameters customisation:
mtq <- mf_get_mtq()
# Plot a choropleth map
mf_map(x = mtq, var = "MED", type = "choro",
pal = "Dark Mint",
breaks = "quantile",
nbreaks = 6,
leg_title = "Median Income\n(euros)",
leg_val_rnd = -2,
leg_pos = "topright")
- Map layout:
mtq <- mf_get_mtq()
# Plot a choropleth map
mf_map(x = mtq, var = "MED", type = "choro",
pal = "Dark Mint",
breaks = "quantile",
nbreaks = 6,
leg_title = "Median Income\n(euros)",
leg_val_rnd = -2,
leg_pos = "topright")
# Plot a layout elements
mf_title("Wealth in Martinique, 2015")
mf_credits("T. Giraud\nSources: INSEE & IGN, 2018")
mf_scale(size = 5)
mf_arrow('topleft')
- Theme:
mtq <- mf_get_mtq()
# Start a map using a theme
mf_init(x = mtq, theme = "dark")
# Plot a choropleth map
mf_map(x = mtq, var = "MED", type = "choro",
pal = "Dark Mint",
breaks = "quantile",
nbreaks = 6,
leg_title = "Median Income\n(euros)",
leg_val_rnd = -2,
leg_pos = "topright",
add = TRUE)
# Plot a layout elements
mf_title("Wealth in Martinique, 2015")
mf_credits("T. Giraud\nSources: INSEE & IGN, 2018")
mf_scale(size = 5)
mf_arrow('topleft')
- Shadow:
mtq <- mf_get_mtq()
# Start a map using a theme
mf_init(x = mtq, theme = "dark")
# Plot a shadow
mf_shadow(mtq, col = "grey10", add = TRUE)
# Plot a choropleth map
mf_map(x = mtq, var = "MED", type = "choro",
pal = "Dark Mint",
breaks = "quantile",
nbreaks = 6,
leg_title = "Median Income\n(euros)",
leg_val_rnd = -2,
leg_pos = "topright",
add = TRUE)
# Plot a layout elements
mf_title("Wealth in Martinique, 2015")
mf_credits("T. Giraud\nSources: INSEE & IGN, 2018")
mf_scale(size = 5)
mf_arrow('topleft')
- Inset
mtq <- mf_get_mtq()
# Start a map using a theme
mf_init(x = mtq, theme = "dark")
# Plot a shadow
mf_shadow(mtq, col = "grey10", add = TRUE)
# Plot a choropleth map
mf_map(x = mtq, var = "MED", type = "choro",
pal = "Dark Mint",
breaks = "quantile",
nbreaks = 6,
leg_title = "Median Income\n(euros)",
leg_val_rnd = -2,
leg_pos = "topright",
add = TRUE)
# Add an inset world map
mf_inset_on(x = "worldmap", pos = "right")
mf_worldmap(mtq, col = "#0E3F5C")
mf_inset_off()
# Plot a layout elements
mf_title("Wealth in Martinique, 2015")
mf_credits("T. Giraud\nSources: INSEE & IGN, 2018")
mf_scale(size = 5)
mf_arrow('topleft')
- Extanded margins
mtq <- mf_get_mtq()
# Start a map using a theme and extra margins
mf_init(x = mtq, theme = "dark",
expandBB = c(0,0,0,.3))
# Plot a shadow
mf_shadow(mtq, col = "grey10", add = TRUE)
# Plot a choropleth map
mf_map(x = mtq, var = "MED", type = "choro",
pal = "Dark Mint",
breaks = "quantile",
nbreaks = 6,
leg_title = "Median Income\n(euros)",
leg_val_rnd = -2,
leg_pos = "topright",
add = TRUE)
# Add an inset world map
mf_inset_on(x = "worldmap", pos = "right")
mf_worldmap(mtq, col = "#0E3F5C")
mf_inset_off()
# Plot a layout elements
mf_title("Wealth in Martinique, 2015")
mf_credits("T. Giraud\nSources: INSEE & IGN, 2018")
mf_scale(size = 5)
mf_arrow('topleft')
Insets
Vignette : How to Create Inset Maps
- With a geographic object
mf_map(mtq)
mf_inset_on(x = mtq[1, ],
cex = .3)
mf_map(mtq[1, ])
mf_inset_off()
- Location inset
mf_map(mtq)
mf_inset_on(x = "worldmap",
pos = "bottomleft")
mf_worldmap(x = mtq)
mf_inset_off()
- Non-cartographic inset
library(mapsf)
library(beeswarm)
mtq <- mf_get_mtq()
# create classes
bks <- mf_get_breaks(x = mtq$MED, nbreaks = 4,
breaks = "quantile")
bks <- round(bks, digits = -2)
# define a color palette
pal <- hcl.colors(n = 4, palette = "Burg", rev = TRUE)
# set a theme
mf_theme("candy")
mf_export(x = mtq, filename = "img/insetbee.svg",
export = "svg",
width = 7,theme = "candy")
fg <-mf_theme()$fg
# Create the map
mf_map(x = mtq, var = "MED", type = "choro",
pal = pal, breaks = bks, leg_pos = NA)
# start the inset
mf_inset_on( fig = c(0.6, .99, 0.86, .99))
# draw the histogram
par(mar = c(0,0,1.7,0))
beeswarm(mtq$MED, vertical = FALSE, cex =1.2,
spacing = .95, axes = FALSE,
pwcol = pal[findInterval(mtq$MED, bks)],
ylim = c(-1,3), pch = 20)
axis(side = 1, at = bks, las = 2, tick = FALSE,
line = -1, cex.axis = .7, col.axis = fg)
abline(v=bks, lwd = .5, lty = 3, col = fg)
title("Median Income\nin euros", cex.main = .8,
col.main = fg, font.main = 1, adj = 0)
# close the inset
mf_inset_off()
# Add map layout
mf_title("Wealth in Martinique, 2015", pos = "left")
mf_scale(5)
mf_credits(paste0("Sources: Insee and IGN, 2018\n",
"mapsf ", packageVersion("mapsf")))
dev.off()
Raster
library(maptiles)
mtq <- st_transform(mtq, 3857)
osm <- get_tiles(
mtq,
provider = "Stamen.TerrainBackground",
crop= TRUE,
zoom = 11
)
th <- mf_theme(
x = "default", bg = "#99b3cc",
inner = TRUE, line = 1.5, cex = 1,
pos = "right", mar = c(0,0,0,0)
)
mf_export(x = osm, filename = "img/osm.png",
width = 672, theme = th, res = 150)
mf_raster(osm)
mf_map(mtq, col = NA, add = TRUE)
mf_scale()
mf_title("mf_raster()")
mf_credits(get_credit("Stamen.TerrainBackground"))
dev.off()
Development
A minimal number of well-known dependancies:
CI/CD with GitHub Actions
Tests with
tinytest, coverage with CodecovInformative commit messages with conventional commits
Other packages
tanaka
Also called “relief contours method,” “illuminated contour method” or “shaded contour lines method,” the Tanaka method enhances the representation of topography on a map by using shaded contour lines. The result is a 3D-like map.
This package is a simplified implementation of the Tanaka method, north-west white contours represent illuminated topography and south-east black contours represent shaded topography.
library(tanaka)
library(elevatr)
# use elevatr to get elevation data
ras <- get_elev_raster(
locations = data.frame(x = c(6.7, 7), y = c(45.8,46)),
z = 10, prj = "EPSG:4326", clip = "locations"
)
# display the map
opar <- par(mar = c(0,3,0,0))
tanaka(x = ras, breaks = seq(500,4800,250),
col = hcl.colors(18,"Inferno"))
par(opar)
Tanaka also can be used with non-topographical data:
linemap
linemap() displays a map made of lines using a data frame of gridded data.
library(linemap)
library(mapsf)
data("popOcc")
occitanie <- st_read(system.file("gpkg/geofla.gpkg",
package = "linemap"),
layer = "Occitanie")
th <- mf_theme(bg = "ivory2")
mf_export(occitanie, width = 800, filename = "img/linemap.png")
mf_map(occitanie, col="ivory1", border = NA)
linemap(x = popOcc, var = "pop", k = 3.25, threshold = 50,
col = "ivory1", border = "ivory4", lwd = 0.6, add = TRUE)
mf_title("Population in Occitanie")
mf_credits("Gridded data 1 km, INSEE 2010")
dev.off()
maptiles
To create maps from tiles, maptiles downloads, composes and displays tiles from a large number of providers (e.g. OpenStreetMap, Stamen, Esri, CARTO, or Thunderforest).
library(sf)
library(maptiles)
hop <- st_read("data/hospital.gpkg", layer = "hospital")
osm <- get_tiles(hop)
th <- mf_theme(mar = c(0,0,0,0), inner = TRUE, line = 2, cex = 1.8)
mf_export(osm, filename = "img/maptiles.png",
width = 768, theme = th)
mf_raster(osm, add = TRUE)
mf_map(hop, "capacity", "prop",
border = "grey", inches = .4,
leg_title = "Number of beds",
leg_frame = TRUE)
mf_title("Public Hospital Capacities in Paris")
mf_credits(get_credit("OpenStreetMap"), bg = "#ffffff80")
dev.off()
The following figure shows mini maps for most of the tiles providers available:
popcircle
This one-function package computes circles with areas scaled to a variable and displays them using a compact layout (higher values in the center, lower values at the periphery). Original polygons are scaled to fit inside these circles (size are roughly proportional, not strictly).
spikemap
It is possible to map quantities with circles, squares or other simple geometric symbols, spikemap uses spikes.
library(sf)
library(spikemap)
library(mapsf)
# import the dataset from the package
com <- st_read(system.file("gpkg/com.gpkg", package="spikemap"),
quiet = TRUE)
mf_map(com, lwd =.2)
spikemap(x = com, var = "pop")
Vielen Dank für Ihre Aufmerksamkeit
sessionInfo()
## R version 4.1.2 (2021-11-01)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Debian GNU/Linux 11 (bullseye)
##
## Matrix products: default
## BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.9.0
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.9.0
##
## locale:
## [1] LC_CTYPE=fr_FR.UTF-8 LC_NUMERIC=C
## [3] LC_TIME=fr_FR.UTF-8 LC_COLLATE=fr_FR.UTF-8
## [5] LC_MONETARY=fr_FR.UTF-8 LC_MESSAGES=fr_FR.UTF-8
## [7] LC_PAPER=fr_FR.UTF-8 LC_NAME=C
## [9] LC_ADDRESS=C LC_TELEPHONE=C
## [11] LC_MEASUREMENT=fr_FR.UTF-8 LC_IDENTIFICATION=C
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] spikemap_0.1.0 elevatr_0.4.1 tanaka_0.1.3 mapsf_0.3.0 sf_1.0-4
##
## loaded via a namespace (and not attached):
## [1] progress_1.2.2 tidyselect_1.1.1 terra_1.4-20 xfun_0.28
## [5] bslib_0.3.1 purrr_0.3.4 lattice_0.20-45 vctrs_0.3.8
## [9] generics_0.1.1 htmltools_0.5.2 s2_1.0.7 yaml_2.2.1
## [13] utf8_1.2.2 rlang_0.4.12 isoband_0.2.5 e1071_1.7-9
## [17] jquerylib_0.1.4 pillar_1.6.4 glue_1.5.0 DBI_1.1.1
## [21] sp_1.4-6 wk_0.5.0 lifecycle_1.0.1 stringr_1.4.0
## [25] progressr_0.9.0 raster_3.5-2 codetools_0.2-18 evaluate_0.14
## [29] knitr_1.36 rmdformats_1.0.3 fastmap_1.1.0 curl_4.3.2
## [33] class_7.3-19 fansi_0.5.0 highr_0.9 Rcpp_1.0.7
## [37] KernSmooth_2.23-20 classInt_0.4-3 jsonlite_1.7.2 hms_1.1.1
## [41] digest_0.6.28 stringi_1.7.5 bookdown_0.24 dplyr_1.0.7
## [45] grid_4.1.2 rgdal_1.5-27 tools_4.1.2 magrittr_2.0.1
## [49] sass_0.4.0 proxy_0.4-26 tibble_3.1.6 crayon_1.4.2
## [53] pkgconfig_2.0.3 ellipsis_0.3.2 prettyunits_1.1.1 httr_1.4.2
## [57] assertthat_0.2.1 rmarkdown_2.11 R6_2.5.1 units_0.7-2
## [61] compiler_4.1.2